#include <iostream>
#include <cstdlib>
#include <cassert>
#include <vector>
#include <ctime>
#include <cstdbool>
#include <map>

#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>

#include "Tack.hpp"

using namespace std;

#define PROCESS_NUM 5

void PublishTack(pid_t childPid,int ChildFd,int command)
{
    // 写入
    write(ChildFd,&command,sizeof(command));

    std::cout<<"接收任务 : "<<"pid: "<<childPid<<"fd: "<<ChildFd<<"command: "<<command<<std::endl;
}

int WaitTack(int fd)
{
    // 读取
    int m=0;
    ssize_t n=read(fd,&m,sizeof(m));

    if(n==0)
    {
        return -1;
    }
    else if(n==4)
    {
        return m;
    }

}

int main(int,char**,char**)
{
    // 装载任务
    LoadTack();

    // pid_t :子进程的pid 
    // int :与相应子进程通信的文件描述符
    vector<std::pair<pid_t,int>> vStoi;

    for(int i=0;i<PROCESS_NUM;i++)
    {
        // 创建管道文件
        int pipeFd[2]={0};

        int ret=pipe(pipeFd);
        assert(ret==0);

        // 创建子进程
        pid_t id = fork();
        assert(id>=0);

        if(id==0) // child
        {
            // 子进程负责读，关闭写端
            close(pipeFd[1]);

            while(true)
            {
                // 等待父进程发布命令
                int command=WaitTack(pipeFd[0]);

                if(command==-1)
                    break;

                vTack[command]();
            }

            exit(1);
        }
        else if(id>0) // father
        {
            // 父进程负责写，关闭读端
            close(pipeFd[0]);

            // 将对应的子进程pid与通信的文件描述符绑定
            vStoi.push_back(pair<pid_t,int>(id,pipeFd[1]));
        }
    }

    srand((size_t)time(nullptr));

    int n=0;

    while(true)
    {
        std::cout<<"*******************************"<<std::endl;
        std::cout<<"**    1,Show   2,execute   ****"<<std::endl;
        std::cout<<"*******************************"<<std::endl;

        std::cin>>n;

        if(n==1)
        {
            ShowTack();
        }
        else if(n==2)
        {
            // 随机布置任务
            int command=rand();

            PublishTack(vStoi[command%vStoi.size()].first,vStoi[command%vStoi.size()].second,command%vTack.size());
        }
        else
        {

        }
    }
    
    // 关闭管道文件
    for(auto &e: vStoi)
    {
        close(e.second);
    }

    // 回收子进程
    for(auto &e: vStoi)
    {
        waitpid(e.first,nullptr,0);
    }

    return 0;
}